昨天看過Parameter後,今天來看看另外一個元件傳遞資料的方式 — Cascading Parameter。
Cascading Parameter與Parameter的差別在於,Parameter是父元件往下一層的子元件傳遞資料,而Cascading Parameter則是可以往父元件下面一連串的子元件傳遞
我們的應用程式就像下圖一樣,是有一連串的元件組合而成的,Parameter的傳遞方式只能往下一層傳遞,以下圖來看,就是Parent傳給C1或C2這2個子元件,那如果要從Parent傳到C3、C4或C5呢? 這時候Cascading Parameter就要上場了。
這邊使用上一篇的Todolist範例,我們要在MainLayout設定color屬性,並讓底下的所有元件都能取得color的值。
首先在MainLayout.razor,我們設定一個color屬性並給預設值red,然後使用CascadingValue將@body包起來,設定Value為@color
<CascadingValue Value="@color">
@Body
</CascadingValue>
@code{
private string color = "red";
}
在Todo元件中,新增一個[CascadingParamter]屬性接收傳來的值,並繫結到tr的style,注意這邊的型別要與Parent設定的一致。
<tr style="color:@color">
<td>@ItemName </td>
<td><button class="btn btn-danger btn-sm" @onclick="Delete">delete</button></td>
</tr>
@code {
//略...
[CascadingParameter]
public string color { get; set; }
}
Todo Item的文字就變紅色囉
現在我們再多傳一個參數size到Todo元件,在MainLayout再多加一個CascadingValue元件
<CascadingValue Value="@color">
<CascadingValue Value="@size">
@Body
</CascadingValue>
</CascadingValue>
@code{
private string color = "red";
private string size = "16px";
}
Todo元件
<tr style="color:@color;font-size:@size;">
<td>@Item</td>
<td><button class="btn btn-danger btn-sm" @onclick="Delete">delete</button></td>
</tr>
@code {
//略...
[CascadingParameter]
public string color { get; set; }
[CascadingParameter]
public string size { get; set; }
}
另外一種寫法是使用class,參考以下程式碼:
<div class="content px-4">
<CascadingValue Value="@state">
@Body
</CascadingValue>
</div>
@code{
State state = new State();
public class State
{
public string color { get; set; } = "red";
public string size { get; set; } = "20px";
}
}
建立State類別(名稱可自訂),將剛剛的color和size設為State類別的屬性,並將CascadingValue元件的Value設為State物件
Todo元件
@using static TodoBlazor.Shared.MainLayout
<tr style="color:@state.color;font-size:@state.size">
<td>@Item</td>
<td><button class="btn btn-danger btn-sm" @onclick="Delete">delete</button></td>
</tr>
@code{
[CascadingParameter]
public State state { get; set; }
}
上面的範例都是直接從MainLayout取值然後顯示,少了一點互動性,現在我們加上幾顆radio button,讓user可以選擇Todo Item文字的顏色。
先在父元件加上顏色的radio button、文字大小的radio button,還有相關的onchage程式碼:
//顏色radio button
<h4 class="font-weight-bold">選擇顏色:</h4>
@foreach (var item in new string[] { "red", "blue", "green" })
{
<div class="custom-control custom-radio">
<input type="radio" id="@item" name="colorRadio" class="custom-control-input" value="@item" @onchange="ColorRadioSelection">
<label class="custom-control-label" for="@item">@item</label>
</div>
}
<br />
//文字radio buttons
<h4 class="font-weight-bold">選擇文字大小:</h4>
@foreach (var item in new string[] { "16px", "20px", "40px" })
{
<div class="custom-control custom-radio">
<input type="radio" id="@item" name="sizeRadio" class="custom-control-input" value="@item" @onchange="SizeRadioSelection">
<label class="custom-control-label" for="@item">@item</label>
</div>
}
@code{
[CascadingParameter]
public State state { get; set; }
void RadioSelection(ChangeEventArgs args)
{
state.color = args.Value.ToString();
}
void SizeRadioSelection(ChangeEventArgs args)
{
state.size = args.Value.ToString();
}
}
另外我們如果在其他元件宣告state這個cascading parameter的話,在Todolist的變更也會反映到其他元件上,例如現在在counter一樣宣告State屬性,並設定h1 Counter的css:
@page "/counter"
@using static TodoBlazor.Shared.MainLayout
<h1 style="color:@state.color;font-size:@state.size">Counter</h1>
<p>Current count: @currentCount</p>
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
@code {
[CascadingParameter]
public State state { get; set; }
private int currentCount = 0;
private void IncrementCount()
{
currentCount++;
}
}
從今天這幾個例子可以知道,父元件Cascading Parameter的Value只要一變更,所有底下的子元件都會偵測到變更,並修改子元件中的Cascading Parameter值,因此如果確定父元件的Cascading Parameter不會變更的話,可以設定IsFixed="true",Blazor就不需要耗費資源去更新子元件了。
<CascadingValue Value="@state" IsFixed="true">
@Body
</CascadingValue>